home *** CD-ROM | disk | FTP | other *** search
/ Turnbull China Bikeride / Turnbull China Bikeride - Disc 2.iso / STUTTGART / LANG / ICON / ICONV8 / Source / Common / C / Dirscan next >
Text File  |  1991-05-24  |  5KB  |  217 lines

  1. /* C.Dirscan: Get filenames for a wildcarded value */
  2.  
  3. /* Use as:
  4.  *
  5.  *    for (file = dirscan(wild); file; file = dirscan(0))
  6.  *        ...
  7.  *
  8.  * Specifying an argument other than 0 restarts the scan with the
  9.  * new wildcard value.
  10.  */ 
  11.  
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <string.h>
  15. #include "kernel.h"
  16. #include "swis.h"
  17.  
  18. /* Constants. The function assumes that a directory can hold no more than
  19.  * MAX_DIR entries, and a filename can be no longer than NAME_LEN characters.
  20.  * It also assumes that OS_GBPB 9 will only ever fail to return all possible
  21.  * filenames on the first call if the supplied buffer becomes full. In this
  22.  * case, dirscan() will ignore any omitted entries. This behaviour is not
  23.  * ideal, but gains significantly in efficiency. (The given buffer size
  24.  * should be easily enough for all normal cases).
  25.  */
  26. #define MAX_DIR        255
  27. #define NAME_LEN    10
  28. #define BUFFER_SIZE    (MAX_DIR * (NAME_LEN + 1))
  29.  
  30. char *dirscan (const char *f)
  31. {
  32.     int len;
  33.     int dot_stripped = 0;
  34.     const char *file;
  35.     _kernel_swi_regs regs;
  36.  
  37.     static char *ptr = NULL;
  38.     static int num_left = 0;
  39.     static char *buffer = NULL;
  40.     static char *name;
  41.     static char res[255];
  42.  
  43.     if (f && *f)
  44.     {
  45.         /* Delete any old buffer */
  46.         if (buffer)
  47.         {
  48.             free (buffer);
  49.             buffer = NULL;
  50.         }
  51.  
  52.         /* Try for a directory prefix */
  53.         file = strrchr (f, '.');
  54.  
  55.         /* If not, try for a filing system prefix */
  56.         if (file == NULL)
  57.         {
  58.             if (*f == '-')
  59.                 file = strchr (f + 1, '-');
  60.             else
  61.                 file = strchr (f, ':');
  62.         }
  63.  
  64.         if (file == NULL)
  65.         {
  66.             /* We have a simple file name, with no directory. So
  67.              * we set name to point to the place to store the
  68.              * file name (ie, res), and we temporarily set res
  69.              * to hold the directory name (ie, ""). We also set
  70.              * file to the file name f.
  71.              */
  72.             name = res;
  73.             file = f;
  74.             name[0] = '\0';
  75.         }
  76.         else
  77.         {
  78.             /* More work to do. Set res up with the directory,
  79.              * as above, and point name to the place to put the
  80.              * file name(s). And set file to the file name.
  81.              */
  82.  
  83.             len = file - f + 1;
  84.  
  85.             /* Do not allow file names over 255 characters
  86.              * (ie, 245 for the directory, and 10 for the
  87.              * base name).
  88.              */
  89.             if (len > 245)
  90.                 return 0;
  91.  
  92.             /* Build the start of the file name to be returned */
  93.             strncpy (res, f, len);
  94.             name = &res[len];
  95.  
  96.             /* Temporarily, put the name of the directory to scan
  97.              * into res. At the moment, res holds "dir." or "FS:"
  98.              * without a NULL terminator. If the former, we must
  99.              * temporarily remove the dot and add a NULL, but if
  100.              * the latter, we must add the current directory
  101.              * name "@".
  102.              */
  103.             if (*file == '.')
  104.             {
  105.                 dot_stripped = name[-1];
  106.                 name[-1] = '\0';
  107.             }
  108.             else
  109.             {
  110.                 name[0] = '@';
  111.                 name[1] = '\0';
  112.             }
  113.  
  114.             /* Now, set file to the base file name */
  115.             ++file;
  116.         }
  117.  
  118.         /* Is the file name wildcarded? */
  119.         if (!strchr (file, '*') && !strchr (file, '#'))
  120.         {
  121.             /* If not, we return the name we were handed,
  122.              * and remember not to return any more later.
  123.              */
  124.  
  125.             /* First restore the proper prefix */
  126.             if (dot_stripped)
  127.                 name[-1] = dot_stripped;
  128.  
  129.             strcpy (name, file);
  130.             num_left = 0;
  131.             return res;
  132.         }
  133.         else
  134.         {
  135.             /* OK, this is the big one. We set up a buffer, and
  136.              * read all the names from the selected directory
  137.              * which match the pattern into it.
  138.              */
  139.  
  140.             buffer = malloc (BUFFER_SIZE) ;
  141.             if (buffer == NULL)
  142.                 return 0;
  143.  
  144.             regs.r[0] = 9;
  145.             regs.r[1] = (int) res;
  146.             regs.r[2] = (int) buffer;
  147.             regs.r[3] = BUFFER_SIZE;
  148.             regs.r[4] = 0;
  149.             regs.r[5] = BUFFER_SIZE;
  150.             regs.r[6] = (int) file;
  151.  
  152.             if (_kernel_swi (OS_GBPB, ®s, ®s))
  153.                 return 0;
  154.  
  155.             /* Now restore the proper prefix */
  156.             if (dot_stripped)
  157.                 name[-1] = dot_stripped;
  158.  
  159.             /* If there were no entries to find, say so */
  160.             if (regs.r[3] == 0)
  161.             {
  162.                 num_left = 0;
  163.                 free (buffer);
  164.                 buffer = NULL;
  165.                 return 0;
  166.             }
  167.  
  168.             /* Remember how many more to return and set ptr
  169.              * ready to return the next one.
  170.              */
  171.             num_left = regs.r[3] - 1;
  172.             ptr = buffer + strlen (buffer) + 1;
  173.  
  174.             /* Return the first one */
  175.             strcpy (name, buffer);
  176.             return res;
  177.         }
  178.     }
  179.  
  180.     /* If we've run out of names to return, free the buffer and stop */
  181.     if (num_left == 0)
  182.     {
  183.         if (buffer)
  184.         {
  185.             free (buffer);
  186.             buffer = NULL;
  187.         }
  188.         return 0;
  189.     }
  190.  
  191.  
  192.     /* Return the next entry in the buffer, and move on in the buffer */
  193.     strcpy (name, ptr);
  194.     ptr += strlen(ptr) + 1;
  195.     --num_left;
  196.  
  197.     return res;
  198. }
  199.  
  200. #ifdef TEST
  201. #include <stdio.h>
  202.  
  203. int main (int argc, char *argv[])
  204. {
  205.     char *name;
  206.  
  207.     while (--argc > 0)
  208.     {
  209.         printf("Scanning %s\n", *++argv);
  210.         for (name = dirscan(*argv); name; name = dirscan(0))
  211.             printf("%s\n", name);
  212.     }
  213.  
  214.     return 0;
  215. }
  216. #endif
  217.